package wangwenjun.phase3.executor.completablefuture.demo02;

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author ChangLiang
 * @date 2020/6/26
 */
@Slf4j
public class AppV3Test {

    private static Integer corePoolSize = 4;

    @Test
    @DisplayName("test")
    public void test(){

        /**
         * 这里虽然是并行的 但是由于futureTask#get是串行的 所以是无法保证整个请求在2秒内返回
         */

        List<String> list = new ArrayList<>();

        log.warn("start");
        long start = System.currentTimeMillis();

        EsService esService = new EsService();

        // 创建4个futureTask
        FutureTask<String> itemsFutureTask = new FutureTask<>(() -> {
            String value;
            try {
                Method method = esService.getClass().getDeclaredMethod("searchQueryItems", String.class);
                Object returnValue = method.invoke(esService, "changliang");
                value = returnValue != null ? returnValue.toString() : null;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
                throw e;
            } catch (SecurityException e) {
                e.printStackTrace();
                throw e;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                throw e;
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
                throw e;
            } catch (InvocationTargetException e) {
                e.printStackTrace();
                throw e;
            }
            return value;
        });

        FutureTask<String> guidesFutureTask = new FutureTask<>(() -> {
            String value;
            try {
                Method method = esService.getClass().getDeclaredMethod("searchQueryGuides", String.class);
                Object returnValue = method.invoke(esService, "changliang");
                value = returnValue != null ? returnValue.toString() : null;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
                throw e;
            } catch (SecurityException e) {
                e.printStackTrace();
                throw e;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                throw e;
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
                throw e;
            } catch (InvocationTargetException e) {
                e.printStackTrace();
                throw e;
            }
            return value;
        });

        FutureTask<String> applicationsFutureTask = new FutureTask<>(() -> {
            String value;
            try {
                Method method = esService.getClass().getDeclaredMethod("getApplications", String.class);
                Object returnValue = method.invoke(esService, "changliang");
                value = returnValue != null ? returnValue.toString() : null;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
                throw e;
            } catch (SecurityException e) {
                e.printStackTrace();
                throw e;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                throw e;
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
                throw e;
            } catch (InvocationTargetException e) {
                e.printStackTrace();
                throw e;
            }
            return value;
        });

        FutureTask<String> appointsFutureTask = new FutureTask<>(() -> {
            String value;
            try {
                Method method = esService.getClass().getDeclaredMethod("getAppointItems", String.class);
                Object returnValue = method.invoke(esService, "changliang");
                value = returnValue != null ? returnValue.toString() : null;
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
                throw e;
            } catch (SecurityException e) {
                e.printStackTrace();
                throw e;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
                throw e;
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
                throw e;
            } catch (InvocationTargetException e) {
                e.printStackTrace();
                throw e;
            }
            return value;
        });

        // 用4个线程来执行
        ThreadPoolExecutor threadPoolExecutor = SearchRequestThreadPool.getExecutor();
        threadPoolExecutor.execute(itemsFutureTask);
        threadPoolExecutor.execute(guidesFutureTask);
        threadPoolExecutor.execute(applicationsFutureTask);
        threadPoolExecutor.execute(appointsFutureTask);

        // 初始化返回值
        String items = null;
        String guides = null;
        String applications = null;
        String appoints = null;

        log.warn("begin get item futureTask");
        // 赋值
        try {
            items = itemsFutureTask.get(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            itemsFutureTask.cancel(true);
            System.out.println("itemsFutureTask.get 方法执行中断");
        } catch (ExecutionException e) {
            itemsFutureTask.cancel(true);
            System.out.println("itemsFutureTask.get Execution异常");
        } catch (TimeoutException e) {
            itemsFutureTask.cancel(true);
            System.out.println("itemsFutureTask.get invoke timeout");
        }
        if (items != null) {
            list.add(items);
        }

        log.warn("begin get guide futureTask");
        try {
            guides = guidesFutureTask.get(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            guidesFutureTask.cancel(true);
            System.out.println("guidesFutureTask.get 方法执行中断");
        } catch (ExecutionException e) {
            guidesFutureTask.cancel(true);
            System.out.println("guidesFutureTask.get Execution异常");
        } catch (TimeoutException e) {
            guidesFutureTask.cancel(true);
            System.out.println("guidesFutureTask.get invoke timeout");
        }
        if (guides != null) {
            list.add(guides);
        }

        log.warn("begin get app futureTask");
        try {
            applications = applicationsFutureTask.get(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            applicationsFutureTask.cancel(true);
            System.out.println("applicationsFutureTask.get 方法执行中断");
        } catch (ExecutionException e) {
            applicationsFutureTask.cancel(true);
            System.out.println("applicationsFutureTask.get Execution异常");
        } catch (TimeoutException e) {
            applicationsFutureTask.cancel(true);
            System.out.println("applicationsFutureTask.get invoke timeout");
        }
        if (applications != null) {
            list.add(applications);
        }

        log.warn("begin get appoint futureTask");
        try {
            appoints = appointsFutureTask.get(2, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            appointsFutureTask.cancel(true);
            System.out.println("appointsFutureTask.get 方法执行中断");
        } catch (ExecutionException e) {
            appointsFutureTask.cancel(true);
            System.out.println("appointsFutureTask.get Execution异常");
        } catch (TimeoutException e) {
            appointsFutureTask.cancel(true);
            System.out.println("appointsFutureTask.get invoke timeout");
        }
        if (appoints != null) {
            list.add(appoints);
        }

        long end = System.currentTimeMillis();

        log.warn("full execution time consumption:{} ms", (end - start));
        log.info("result:{}", list);
    }

}


